package boboLang;
/*
* created by 许波波 on 2017/12/29
* 抄一遍String类
* */

import com.sun.org.apache.xerces.internal.impl.xpath.regex.Match;

import java.io.Serializable;
import java.util.Arrays;

//final表明该类不能被继承
public final class BoboString implements Serializable, Comparable<BoboString>, CharSequence{

    /*
    *  final表明value值一旦确定就不能修改
    *  String类实际上就是用这个字符数组进行存储的
    * */
    private final char[] value;

    /*存储hash值，默认值为0*/
    private int hash;

    /*
    * 一系列构造函数
    * */

    public BoboString(){
        //String类中这样实现： this.value = "".value;
        this.value = new char[0];
    }

    /*通过字符串构造*/
    public BoboString(BoboString original){
        this.value = original.value;
        this.hash = original.hash;
    }

    /*通过字符数组来构造*/
    public BoboString(char[] value){
        this.value = Arrays.copyOf(value, value.length);
    }

    /*通过字符数组的一部分来构造*/
    public BoboString(char[] value, int offset, int count){
        if (offset < 0){
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0){
            throw new StringIndexOutOfBoundsException(count);
        }

        if (offset + count > value.length){
            throw new StringIndexOutOfBoundsException(offset + count);
        }

        this.value = Arrays.copyOfRange(value, offset, offset + count);
    }

    /*通过字节数组来构造，需要指定编码方式，暂时不写*/

    /*通过StringBuffer来构造*/
    /*通过StringBuilder来构造*/

    /*
    *  包私有，share只能为true，直接内存指向
    *  性能好，该对象的value直接传入的参数地址
    *  因为是包内共享，所以是安全的，外界无法调用该方法，所以就不可能修改value
    *  加一个share，必须为true，只是为了区别BoboString(char[] value)函数
    * */
    BoboString(char[] value, boolean share){
        // assert share : "unshared not supported";
        this.value = value;
    }

    /*
    * 其他一般方法
    * */

    /*是否为空*/
    public boolean isEmpty(){
        return this.value.length == 0;
    }


    /*
    * 重写hashCode和Equals
    * */
    @Override
    public int hashCode() {
        int h = hash;
        if (h == 0 & value.length > 0){
            char[] val = this.value;
            for (int i=0; i<value.length; i++){
                h = h * 31 + val[i];
            }
            hash = h;
        }
        return h;
    }

    @Override
    public boolean equals(Object obj) {
        //就是同一个对象，直接返回true
        if (this == obj){
            return true;
        }

        if (obj instanceof BoboString){
            BoboString bs = (BoboString)obj;
            int n = value.length;
            if (n == bs.value.length){
                char[] v1 = bs.value;
                char[] v2 = this.value;
                for (int i=0; i<n; i++){
                    if (v1[i] != v2[i]){
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    }

    public BoboString subString(int beginIndex, int endIndex){
        if (beginIndex < 0){
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length){
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        if (beginIndex > endIndex){
            throw new StringIndexOutOfBoundsException(beginIndex - endIndex);
        }

        return ((beginIndex == 0) && (endIndex == value.length)) ? this : new BoboString(value, beginIndex, endIndex-beginIndex);
    }

    public BoboString trim(){
        int beginIndex = 0, endIndex = value.length;
        char[] val = value;

        while ((beginIndex < endIndex) && (val[beginIndex] <= ' ')){
            beginIndex++;
        }
        while ((beginIndex < endIndex) && (val[endIndex - 1] <= ' ')){
            endIndex--;
        }

        return ((beginIndex > 0) || (endIndex < val.length)) ? subString(beginIndex, endIndex) : this;
    }

    /*
    * 复制该字符串中的字符到目的字符数组
    * */
    public void getChars(int srcBegin, int srcEnd, char[] dst,int dstBegin){
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }
    @Override
    public int length() {
        return value.length;
    }

    @Override
    public char charAt(int index) {
        if ((index < 0) || (index >= value.length)){
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        return null;
    }

    @Override
    public int compareTo(BoboString bs) {
        int len1 = value.length;
        int len2 = bs.value.length;
        int min = Math.min(len1, len2);
        char[] v1 = value;
        char[] v2 = bs.value;

        for (int i=0; i<min; i++){
            if (v1[i] != v2[i]){
                return v1[i] - v2[i];
            }
        }
        return len1 - len2;
    }
}
